package com.self.cloudmall.pms.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.self.cloudmall.common.constant.PmsConstant;
import com.self.cloudmall.common.dto.CartItemCheckedDto;
import com.self.cloudmall.common.utils.R;
import com.self.cloudmall.pms.client.SeckillClient;
import com.self.cloudmall.pms.entity.*;
import com.self.cloudmall.pms.mapper.SkuInfoMapper;
import com.self.cloudmall.pms.service.SkuImagesService;
import com.self.cloudmall.pms.service.SkuInfoService;
import com.self.cloudmall.pms.service.SkuSaleAttrValueService;
import com.self.cloudmall.pms.service.SpuInfoDescService;
import com.self.cloudmall.pms.utils.PageUtils;
import com.self.cloudmall.pms.utils.Query;
import com.self.cloudmall.pms.vo.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.stream.Collectors;


@Service("skuInfoService")
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfoEntity> implements SkuInfoService {

    @Autowired
    private SkuImagesService skuImagesService;
    @Autowired
    private SkuSaleAttrValueService skuSaleAttrValueService;
    @Autowired
    private SpuInfoDescService spuInfoDescService;
    @Autowired
    private ThreadPoolExecutor executor;
    @Autowired
    private SeckillClient seckillClient;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                new QueryWrapper<SkuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean batchSaveSkuRelation(List<SkuVo> skus, SpuInfoEntity spuInfoEntity) {
        for (SkuVo vo : skus){
            SkuInfoEntity skuInfoEntity = new SkuInfoEntity();
            assembleSkuInfo(skuInfoEntity,vo,spuInfoEntity);
            this.baseMapper.insert(skuInfoEntity);
            vo.setSkuId(skuInfoEntity.getSkuId());
            List<ImageVo> images = vo.getImages();
            if (!CollectionUtils.isEmpty(images)){
                List<SkuImagesEntity> collect = images.stream()
                        .filter(x -> x != null && StringUtils.isNotEmpty(x.getImgUrl()))
                        .map(x -> {
                    SkuImagesEntity imagesEntity = new SkuImagesEntity();
                    imagesEntity.setDefaultImg(x.getDefaultImg());
                    imagesEntity.setImgUrl(x.getImgUrl());
                    imagesEntity.setSkuId(skuInfoEntity.getSkuId());
                    return imagesEntity;
                }).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(collect)){
                    skuImagesService.saveBatch(collect);
                }
            }
            List<SkuAttrVo> attrs = vo.getAttr();
            if (!CollectionUtils.isEmpty(attrs)){
                List<SkuSaleAttrValueEntity> list = attrs.stream().map(x -> {
                    SkuSaleAttrValueEntity saleAttrValueEntity = new SkuSaleAttrValueEntity();
                    saleAttrValueEntity.setAttrId(x.getAttrId());
                    saleAttrValueEntity.setAttrName(x.getAttrName());
                    saleAttrValueEntity.setAttrValue(x.getAttrValue());
                    saleAttrValueEntity.setSkuId(skuInfoEntity.getSkuId());
                    return saleAttrValueEntity;
                }).collect(Collectors.toList());
                if (!CollectionUtils.isEmpty(list)){
                    skuSaleAttrValueService.saveBatch(list);
                }
            }

        }

        return true;
    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params) {
        QueryWrapper<SkuInfoEntity> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<SkuInfoEntity> lambda = queryWrapper.lambda();
        String key = (String) params.get("key");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(key)){
            lambda.and(w -> w.eq(SkuInfoEntity::getSkuId,key).or().like(SkuInfoEntity::getSkuName,key));
        }
        String brandId = (String) params.get("brandId");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(brandId) && !"0".equals(brandId)){
            lambda.eq(SkuInfoEntity::getBrandId,Long.parseLong(brandId));
        }
        String catelogId = (String) params.get("catelogId");
        if (org.apache.commons.lang.StringUtils.isNotEmpty(catelogId) && !"0".equals(catelogId)){
            lambda.eq(SkuInfoEntity::getCatalogId,Long.parseLong(catelogId));
        }
        String min = (String) params.get("min");
        if (StringUtils.isNotEmpty(min)){
            BigDecimal priceMin = new BigDecimal(min);
            if (priceMin.compareTo(BigDecimal.ZERO) >= 0){
                lambda.ge(SkuInfoEntity::getPrice,priceMin);
            }
        }
        String max = (String) params.get("max");
        if (StringUtils.isNotEmpty(max)){
            BigDecimal priceMax = new BigDecimal(max);
            if (priceMax.compareTo(BigDecimal.ZERO) > 0){
                lambda.le(SkuInfoEntity::getPrice,priceMax);
            }
        }
        IPage<SkuInfoEntity> page = this.page(
                new Query<SkuInfoEntity>().getPage(params),
                queryWrapper
        );
        return new PageUtils(page);
    }

    @Override
    public List<SkuInfoEntity> querySkusBySpuId(Long spuId) {
        return this.lambdaQuery().eq(SkuInfoEntity::getSpuId,spuId).list();
    }

    @Override
    public SkuItemVo getItem(Long skuId) {
        SkuItemVo itemVo = new SkuItemVo();
        //sku信息
        CompletableFuture<SkuInfoEntity> skuInfoFuture = CompletableFuture.supplyAsync(() -> {
            SkuInfoEntity infoEntity = this.getById(skuId);
            SkuInfoVo infoVo = new SkuInfoVo();
            BeanUtils.copyProperties(infoEntity, infoVo);
            itemVo.setSkuInfo(infoVo);
            return infoEntity;
        }, executor);

        //sku图片
        CompletableFuture<Void> skuImageFuture = CompletableFuture.runAsync(() -> {
            List<SkuImagesEntity> list = skuImagesService.lambdaQuery().eq(SkuImagesEntity::getSkuId, skuId)
                    .list();
            if (!CollectionUtils.isEmpty(list)) {
                List<SkuImagesVo> collect = list.stream().map(x -> {
                    SkuImagesVo imagesVo = new SkuImagesVo();
                    BeanUtils.copyProperties(x, imagesVo);
                    return imagesVo;
                }).collect(Collectors.toList());
                itemVo.setSkuImages(collect);
            }
        });
        //spu的销售属性
        CompletableFuture<Void> saleAttrFuture =  skuInfoFuture.thenAcceptAsync(res -> {
            List<SkuItemSaleAttrVo> saleAttrVos = this.baseMapper.querySkuItemSaleAttr(res.getSpuId());
            itemVo.setSaleAttrs(saleAttrVos);
        },executor);

        //spu介绍
        CompletableFuture<Void> spuInfoFuture = skuInfoFuture.thenAcceptAsync(res -> {
            SpuInfoDescEntity spuDesc = spuInfoDescService.getById(res.getSpuId());
            if (spuDesc != null){
                itemVo.setDecript(spuDesc.getDecript());
            }
        },executor);

        //spu的规格参数
        CompletableFuture<Void> spuAttrFuture = skuInfoFuture.thenAcceptAsync(res -> {
            List<SpuBaseGroupAttrVo> spuBaseGroupAttrVos = this.baseMapper.querySpuBaseGroupAttr(res.getSpuId(), res.getCatalogId());
            itemVo.setGroupAttrVos(spuBaseGroupAttrVos);
        }, executor);

        //获取秒杀信息
        CompletableFuture<Void> seckillFuture =  CompletableFuture.runAsync(()->{
            R seckillSkuBySkuId = seckillClient.getSeckillSkuBySkuId(skuId);
            if (seckillSkuBySkuId.isSuccess()){
                SeckillSkuVo seckillSkuVo = JSONObject.parseObject(JSONObject.toJSONString(seckillSkuBySkuId.getData()),
                        SeckillSkuVo.class);
                itemVo.setSeckillSku(seckillSkuVo);
            }
        }, executor);

        //全部执行完，返回结果
        try {
            CompletableFuture.allOf(skuImageFuture,saleAttrFuture,spuInfoFuture,spuAttrFuture,seckillFuture).get();
        } catch (Exception e) {
            log.error("获取详情页数据报错：{}",e);
        }

        return itemVo;
    }

    @Override
    public R getSaleAttrs(Long skuId) {
        List<String> list = this.baseMapper.getSaleAttrs(skuId);
        return R.ok().setData(list);
    }

    @Override
    public List<CartItemCheckedDto> getSkus(List<Long> skuIds) {
        List<SkuInfoEntity> list = this.lambdaQuery().in(SkuInfoEntity::getSkuId, skuIds).list();
        if (!CollectionUtils.isEmpty(list)){
            return list.stream().map(x ->{
                CartItemCheckedDto cartItemChecked = new CartItemCheckedDto();
                cartItemChecked.setSkuId(cartItemChecked.getSkuId());
                cartItemChecked.setPrice(x.getPrice());
                return cartItemChecked;
            }).collect(Collectors.toList());
        }
        return null;
    }

    private void assembleSkuInfo(SkuInfoEntity skuInfoEntity, SkuVo vo, SpuInfoEntity spuInfoEntity) {
        skuInfoEntity.setSpuId(spuInfoEntity.getId());
        skuInfoEntity.setBrandId(spuInfoEntity.getBrandId());
        skuInfoEntity.setCatalogId(spuInfoEntity.getCatalogId());
        skuInfoEntity.setPrice(vo.getPrice());
        skuInfoEntity.setSkuName(vo.getSkuName());
        skuInfoEntity.setSkuTitle(vo.getSkuTitle());
        skuInfoEntity.setSkuSubtitle(vo.getSkuSubtitle());
        skuInfoEntity.setSaleCount(0L);
        skuInfoEntity.setSkuDefaultImg(getDefaultImg(vo));
    }

    private String getDefaultImg(SkuVo vo) {
        List<ImageVo> images = vo.getImages();
        if (!CollectionUtils.isEmpty(images)){
            for (ImageVo img : images){
                if (img.getDefaultImg() == PmsConstant.DEFAULT){
                    return img.getImgUrl();
                }
            }
        }
        return null;
    }

}